// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`annot.js 1`] = `
function foo(str:string, i:number):string {
  return str;
}
var bar: (str:number, i:number)=> string = foo;

var qux = function(str:string, i:number):number { return foo(str,i); }

var obj: {str:string; i:number; j:boolean} = {str: "...", i: "...", k: false};

var arr: Array<number> = [1,2,"..."];

// array sugar
var array: number[] = [1,2,"..."];

var matrix: number[][] = [[1,2],[3,4]];
var matrix_parens: (number[])[] = matrix;

var nullable_array: ?number[] = null;
var nullable_array_parens: ?(number[]) = nullable_array;

var array_of_nullable: (?number)[] = [null, 3];

var array_of_tuple: [number, string][] = [[0, "foo"], [1, "bar"]];
var array_of_tuple_parens: ([number, string])[] = array_of_tuple;

type ObjType = { 'bar-foo': string; 'foo-bar': number; };
var test_obj: ObjType = { 'bar-foo': '23' };

// param type annos are strict UBs like var type annos
function param_anno(n:number):void {
  n = "hey"; // error
}

// another error on param UB, more typical of www (mis)use-cases
// this one cribbed from API.atlas.js
function param_anno2(
    batchRequests: Array<{method: string; path: string; params: ?Object}>,
  ): void {

    // error below, since we're assigning elements to batchRequests
    // which lack a path property.
    // just assign result to new var instead of reassigning to param.

    // Transform the requests to the format the Graph API expects.
    batchRequests = batchRequests.map((request) => {
      return {
        method: request.method,
        params: request.params,
        relative_url: request.path,
      };
    });
    // ...
  }

var toz : null = 3;

var zer : null = null;

function foobar(n : ?number) : number | null | void { return n; }
function barfoo(n : number | null | void) : ?number { return n; }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function foo(str: string, i: number): string {
  return str;
}
var bar: (str: number, i: number) => string = foo;

var qux = function(str: string, i: number): number {
  return foo(str, i);
};

var obj: { str: string, i: number, j: boolean } = {
  str: "...",
  i: "...",
  k: false
};

var arr: Array<number> = [1, 2, "..."];

// array sugar
var array: number[] = [1, 2, "..."];

var matrix: number[][] = [[1, 2], [3, 4]];
var matrix_parens: number[][] = matrix;

var nullable_array: ?(number[]) = null;
var nullable_array_parens: ?(number[]) = nullable_array;

var array_of_nullable: (?number)[] = [null, 3];

var array_of_tuple: [number, string][] = [[0, "foo"], [1, "bar"]];
var array_of_tuple_parens: [number, string][] = array_of_tuple;

type ObjType = { "bar-foo": string, "foo-bar": number };
var test_obj: ObjType = { "bar-foo": "23" };

// param type annos are strict UBs like var type annos
function param_anno(n: number): void {
  n = "hey"; // error
}

// another error on param UB, more typical of www (mis)use-cases
// this one cribbed from API.atlas.js
function param_anno2(
  batchRequests: Array<{ method: string, path: string, params: ?Object }>
): void {
  // error below, since we're assigning elements to batchRequests
  // which lack a path property.
  // just assign result to new var instead of reassigning to param.

  // Transform the requests to the format the Graph API expects.
  batchRequests = batchRequests.map(request => {
    return {
      method: request.method,
      params: request.params,
      relative_url: request.path
    };
  });
  // ...
}

var toz: null = 3;

var zer: null = null;

function foobar(n: ?number): number | null | void {
  return n;
}
function barfoo(n: number | null | void): ?number {
  return n;
}

`;

exports[`forward_ref.js 1`] = `
let myClassInstance: MyClass = null; // forward ref ok, null ~> class error

function bar(): MyClass {
  return null; // forward ref ok, null ~> class error
}

class MyClass { } // looked up above

function foo() {
  let myClassInstance: MyClass = mk(); // ok (no confusion across scopes)
  function mk() { return new MyClass(); }

  class MyClass { } // looked up above
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
let myClassInstance: MyClass = null; // forward ref ok, null ~> class error

function bar(): MyClass {
  return null; // forward ref ok, null ~> class error
}

class MyClass {} // looked up above

function foo() {
  let myClassInstance: MyClass = mk(); // ok (no confusion across scopes)
  function mk() {
    return new MyClass();
  }

  class MyClass {} // looked up above
}

`;

exports[`issue-530.js 1`] = `
function foo(...args: any) { }

module.exports = foo;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function foo(...args: any) {}

module.exports = foo;

`;

exports[`leak.js 1`] = `
/** @flow */

/* This test documents an example we ran into of a type annotation leaking.
 *
 * When foo() calls bar(), we should make sure the type of x matches the type
 * annotation for y and stop. We should type the body of bar() with the type
 * annotation of y.
 *
 * However, the leaky type annotation meant that we were flowing x's type to y
 * and type checking the body of bar() using the stricter dictionary type,
 * leading to an error.
 */

type MyObj = Object;

function foo(x: {[key: string]: mixed}) {
  bar(x);
}

function bar(y: MyObj): string {
  return y.foo;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/** @flow */

/* This test documents an example we ran into of a type annotation leaking.
 *
 * When foo() calls bar(), we should make sure the type of x matches the type
 * annotation for y and stop. We should type the body of bar() with the type
 * annotation of y.
 *
 * However, the leaky type annotation meant that we were flowing x's type to y
 * and type checking the body of bar() using the stricter dictionary type,
 * leading to an error.
 */

type MyObj = Object;

function foo(x: { [key: string]: mixed }) {
  bar(x);
}

function bar(y: MyObj): string {
  return y.foo;
}

`;

exports[`other.js 1`] = `
class C { }
module.exports = (C: any);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class C {}
module.exports = (C: any);

`;

exports[`scope.js 1`] = `
type Merge<T> = (a: T, b: T) => T;

// hypothetical immutable map
declare class Map<K,V> {
  (): Map<K,V>;
  insertWith(fn: Merge<V>, k: K, v: V): Map<K,V>;
}

declare function foldr<A,B>(fn: (a: A, b: B) => B, b: B, as: A[]): B;

function insertMany<K,V>(merge: Merge<V>, vs: [K,V][], m: Map<K,V>): Map<K,V> {
  function f([k,v]: [K,V], m: Map<K,V>): Map<K,V> {
    return m.insertWith(merge, k, v)
  }
  return foldr(f, m, vs)
}

class Foo<A> {
  bar<B>() {
    return function<C>(a: A, b: B, c: C): void {
      ([a,b,c] : [A,B,C]);
    }
  }
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
type Merge<T> = (a: T, b: T) => T;

// hypothetical immutable map
declare class Map<K, V> {
  (): Map<K, V>;
  insertWith(fn: Merge<V>, k: K, v: V): Map<K, V>;
}

declare function foldr<A, B>(fn: (a: A, b: B) => B, b: B, as: A[]): B;

function insertMany<K, V>(
  merge: Merge<V>,
  vs: [K, V][],
  m: Map<K, V>
): Map<K, V> {
  function f([k, v]: [K, V], m: Map<K, V>): Map<K, V> {
    return m.insertWith(merge, k, v);
  }
  return foldr(f, m, vs);
}

class Foo<A> {
  bar<B>() {
    return function<C>(a: A, b: B, c: C): void {
      ([a, b, c]: [A, B, C]);
    };
  }
}

`;

exports[`test.js 1`] = `
var C = require('./other');
((0: C): string);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
var C = require("./other");
((0: C): string);

`;
